package io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor;

import org.junit.jupiter.api.Test;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.element.BooleanElement;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.element.CollectionElement;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.element.IntegerElement;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.element.StringElement;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.element.Visitable;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.visitor.ByteLengthVisitor;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.visitor.HashCodeVisitor;
import io.gitee.yth.design.pattern.test.core.pattern.behavioral.visitor.visitor.Visitor;

import java.util.ArrayList;
import java.util.List;

/**
 * 访问者模式不适用的场景：element类频繁增添、element类的接口功能不够强大
 * <p>
 * 访问者模式适用的场景：visitor类频繁增添
 * <p>
 * 谁负责遍历对象结构的每一个元素？
 * 1. 对象结构（通常）
 * 2. 使用迭代器模式
 * 3. Visitor自定义遍历方案
 *
 * @author yth
 * @since 2023-04-29-16:48
 */
public class Client {

    private static final Visitable BOOLEAN_ELEMENT1;
    private static final Visitable BOOLEAN_ELEMENT2;
    private static final Visitable STRING_ELEMENT;
    private static final Visitable INTEGER_ELEMENT1;
    private static final Visitable INTEGER_ELEMENT2;
    private static final Visitable COLLECTION_ELEMENT;

    private static final ObjectStructure OBJECT_STRUCTURE;

    static {
        BOOLEAN_ELEMENT1 = new BooleanElement(true);
        BOOLEAN_ELEMENT2 = new BooleanElement(false);
        STRING_ELEMENT = new StringElement("helloWorld");
        INTEGER_ELEMENT1 = new IntegerElement(123);
        INTEGER_ELEMENT2 = new IntegerElement(123);

        final List<Visitable> list = new ArrayList<>();
        list.add(BOOLEAN_ELEMENT1);
        list.add(BOOLEAN_ELEMENT2);
        list.add(STRING_ELEMENT);
        list.add(INTEGER_ELEMENT1);
        list.add(INTEGER_ELEMENT2);

        COLLECTION_ELEMENT = new CollectionElement(list);

        OBJECT_STRUCTURE = new ObjectStructure();
        OBJECT_STRUCTURE.addAll(list);
    }

    @Test
    public void test1() {
        final Visitor hashCodeVisitor = new HashCodeVisitor();
        final ByteLengthVisitor byteLengthVisitor = new ByteLengthVisitor();

        COLLECTION_ELEMENT.accept(hashCodeVisitor);
        COLLECTION_ELEMENT.accept(byteLengthVisitor);
        System.out.println("byteLengthVisitor.getLength() = " + byteLengthVisitor.getLength());
    }

    @Test
    public void test2() {
        OBJECT_STRUCTURE.remove(BOOLEAN_ELEMENT1);
        final Visitor hashCodeVisitor = new HashCodeVisitor();
        final ByteLengthVisitor byteLengthVisitor = new ByteLengthVisitor();

        OBJECT_STRUCTURE.accept(hashCodeVisitor);
        OBJECT_STRUCTURE.accept(byteLengthVisitor);
        System.out.println("byteLengthVisitor.getLength() = " + byteLengthVisitor.getLength());
    }

}
